package com.demo.gateway.exception;

import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;

import com.alibaba.fastjson.JSON;
import com.demo.gateway.util.DateUtil;

/**
 * @author: demo
 * @date: 2020年6月18日
 * @Document : 异常处理类
 */
public class JsonErrorHandler extends DefaultErrorWebExceptionHandler {
	
	private  static final String  IGNORE_URL_ERROR="/favicon.ico";
	private Logger logger = LoggerFactory.getLogger(getClass());

	public JsonErrorHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties,
			ErrorProperties errorProperties, ApplicationContext applicationContext) {
		super(errorAttributes, resourceProperties, errorProperties, applicationContext);
	}

	/**
	 * 自定义异常处理
	 */
	@Override
	protected Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
		Throwable error = super.getError(request);
		return getRequestErrorBody(request, error);
	}

	/**
	 * 指定响应处理方法为JSON处理的方法
	 * 
	 * @param errorAttributes
	 */
	@Override
	protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
		return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
	}

	/**
	 * 设置HttpStatus 为errorCode
	 */
	@Override
	protected HttpStatus getHttpStatus(Map<String, Object> errorAttributes) {
		logger.warn(JSON.toJSON(errorAttributes).toString());
		int errorCode = (int) errorAttributes.get("errorCode");
		return HttpStatus.valueOf(errorCode);
	}

	/**
	 * 处理请求体
	 */
	public Map<String, Object> getRequestErrorBody(ServerRequest request, Throwable error) {
		Map<String, Object> errorBody = new HashMap<String, Object>(10);
		String  uri= request.uri().toString();
		if (uri.contains(IGNORE_URL_ERROR)) {
			errorBody.put("uri",uri);
			errorBody.put("errorCode", 404);
			return errorBody;
		}
		logger.error("gateway-server异常==> {}", error);
		errorBody.put("url",uri);
		errorBody.put("type", request.methodName());
		if (error != null) {
			errorBody.put("errorMsg", error.getMessage());
		}
		int errorCode = 500;
		if (error instanceof org.springframework.cloud.gateway.support.NotFoundException) {
			errorCode = 404;
		} else if (error instanceof org.springframework.cloud.gateway.support.TimeoutException) {
			errorCode = 500;
		}
		errorBody.put("errorCode", errorCode);
		errorBody.put("errorTime", DateUtil.getNow());
		return errorBody;
	}

}
